/*
Copyright 2010  Murali Devi (profdevi@gmail.com)

This file is part of ComineGL Project.

ComineGL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

ComineGL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with ComineGL.  If not, see <http://www.gnu.org/licenses/>.

This code uses the irrlicht and irrklang libraries.  Please read
the libraries copyrights at 

	irrlicht library:  http://irrlicht.sourceforge.net
	irrklang library:  http://www.ambiera.com/irrklang

*/



//v0.16 copyright Comine.com 20110925U16
#include "MStdLib.h"
#include "MIrrklang.h"
#include "MIrrlicht.h"
#include "MCGLNodeInfo.h"
#include "MCGLTextureInfo.h"
#include "MCGLSoundInfo.h"
#include "MCGLMeshInfo.h"
#include "MCGLFontInfo.h"
#include "MCGLAnimationInfo.h"
#include "MCGLEventInput.h"
#include "MCGLTriangleSelectorInfo.h"
#include "MTimeEventQueue.h"
#include "TRefCount.h"
#include "TIntRefCountMap.h"
#include "MCGLCameraControl.h"
#include "Global.h"


//////////////////////////////////////////////////
// Module Elements
//////////////////////////////////////////////////
const char GlobalVersion[]="0.16";


////////// Global Variables /////////////////////
bool GlobalInitialized=false;							// =true if Module is initialized
IrrlichtDevice *GlobalRefDevice=NULL;					// Reference to Irrlicht Device
IVideoDriver *GlobalRefVideoDriver=NULL;				// Reference to Irrlicht Video Driver
ISceneManager *GlobalRefSceneMgr=NULL;					// Reference to Irrlicht Scene Manager
IFileSystem *GlobalRefFileSystem=NULL;					// Reference to Irrlicht File System
ICursorControl *GlobalRefCursorControl=NULL;			// Reference to Irrlicht Cursor Control
ITimer *GlobalRefTimer=NULL;							// Reference to Irrlicht Timer
ISceneCollisionManager *GlobalRefCollisionMgr=NULL;		// Reference to Irrlicht Collision Mgr
IGUIEnvironment *GlobalRefGUIEnvironment=NULL;			// Reference to Irrlicht GUI Environment
ISoundEngine *GlobalRefSoundDevice=NULL;				// Reference to irrKlang Device
SColor GlobalBackColor=SColor(255,0x60,0xA0,0xA0);		// Set Default Back COlor
bool (*GlobalWindowFrontRenderer)(void)=NULL;			// Callback for front renderer
bool (*GlobalWindowBackRenderer)(void)=NULL;			// Callback for back renderer
bool GlobalGameLoopBreakFlag=false;							// =true if game loop should break


//////////////////////////////////////////////////////////
TIntRefCountMap<MCGLNodeInfo> GlobalNodeList;			// List of all nodes in scene graph
TIntRefCountMap<MCGLTextureInfo> GlobalTextureList;		// List of all textures
TIntRefCountMap<MCGLSoundInfo> GlobalSoundList;			// List of all nodes in scene graph
TIntRefCountMap<MCGLMeshInfo> GlobalMeshList;			// List of all meshs
TIntRefCountMap<MCGLFontInfo> GlobalFontList;			// List of all fonts
TIntRefCountMap<MCGLAnimationInfo> GlobalAnimationList;	// List of all fonts
TIntRefCountMap<MCGLTriangleSelectorInfo> GlobalTrisetList;	// List of all Triangle Sets(Called Triangle Selectors in Irrlicht)
TIntRefCountMap<MIntArray> GlobalIntArrayList;			// List of all MIntArrays
MCGLEventInput GlobalEventInput;						// Event receiver for input devices
MTimeEventQueue GlobalTaskQueue;						// Set of all Tesks
MTimeEventQueue GlobalTaskQueueInternal;				// Internal Task Queue
MCGLCameraControl GlobalCameraControl;					// Holds information about key mappings for camera
int GlobalInternalEventID;								// Internal Event ID

/////////////////////////////////////////////////
// Module Elements
bool GlobalClear(void)
	{
	GlobalInitialized=false;
	GlobalRefDevice=NULL;
	GlobalRefVideoDriver=NULL;
	GlobalRefSceneMgr=NULL;
	GlobalRefFileSystem=NULL;
	GlobalRefCursorControl=NULL;
	GlobalRefTimer=NULL;
	GlobalRefCollisionMgr=NULL;
	GlobalRefGUIEnvironment=NULL;
	GlobalRefSoundDevice=NULL;
	GlobalInternalEventID=0;

	// Rendering for back and front
	GlobalWindowFrontRenderer=NULL;
	GlobalWindowBackRenderer=NULL;
	return true;
	}


//////////////////////////////////////////////////
bool GlobalCreate(int width,int height,int bpp,bool fullscreen )
	{
	GlobalDestroy();

	MStdPrintf("ComineGL Library version %s\n",GlobalVersion);

	MStdPrintf("Starting Initialization of Irrlicht Library\n");

	// Init Irrlicht device
	if((GlobalRefDevice=createDevice(EDT_DIRECT3D9,dimension2d<u32>(width,height)
				,bpp,fullscreen,false,false,&GlobalEventInput))!=NULL)
		{
		//=We have initialized irrlicht
		}
	else if((GlobalRefDevice=createDevice(EDT_DIRECT3D8,dimension2d<u32>(width,height)
			,bpp,fullscreen,false,false,&GlobalEventInput))!=NULL)
		{
		//=We have initialized irrlicht
		}
	else if((GlobalRefDevice=createDevice(EDT_OPENGL,dimension2d<u32>(width,height)
			,bpp,fullscreen,false,false,&GlobalEventInput))!=NULL)
		{
		//=We have initialized irrlicht
		}
	else if((GlobalRefDevice=createDevice(EDT_SOFTWARE,dimension2d<u32>(width,height)
			,bpp,fullscreen,false,false,&GlobalEventInput))!=NULL)
		{
		//=We have initialized irrlicht
		}
	else
		{
		GlobalDestroy();
		return false;
		}

	// Get References to other interfaces
	GlobalRefVideoDriver=GlobalRefDevice->getVideoDriver();
	GlobalRefSceneMgr=GlobalRefDevice->getSceneManager();
	GlobalRefFileSystem=GlobalRefDevice->getFileSystem();
	GlobalRefCursorControl=GlobalRefDevice->getCursorControl();
	GlobalRefTimer=GlobalRefDevice->getTimer();
	GlobalRefCollisionMgr=GlobalRefSceneMgr->getSceneCollisionManager();
	GlobalRefGUIEnvironment=GlobalRefDevice->getGUIEnvironment();

	MStdPrintf("Starting Initialization of Irrklang Library\n");
	// Init the sound
	GlobalRefSoundDevice=createIrrKlangDevice();
	if(GlobalRefSoundDevice==NULL)
		{
		GlobalDestroy();
		return false;
		}
	
	// Init Node Table
	if(GlobalNodeList.Create()==false)
		{
		MStdPrintf("**Node List Failure\n");
		GlobalDestroy();
		return false;
		}

	// Init Texture Table
	if(GlobalTextureList.Create()==false)
		{
		MStdPrintf("**Texture List Failure\n");
		GlobalDestroy();
		return false;
		}

	// Init Sound Table
	if(GlobalSoundList.Create()==false)
		{
		MStdPrintf("**Sound List Failure\n");
		GlobalDestroy();
		return false;
		}

	// Init Mesh Table
	if(GlobalMeshList.Create()==false)
		{
		MStdPrintf("**Mesh Table failed\n");
		GlobalDestroy();
		return false;
		}

	// Init Font Table
	if(GlobalFontList.Create()==false)
		{
		MStdPrintf("**Font Table failed\n");
		GlobalDestroy();
		return false;
		}

	// Init Animation Table
	if(GlobalAnimationList.Create()==false)
		{
		MStdPrintf("**Animation Table failed\n");
		GlobalDestroy();
		return false;
		}

	// Init Triangle Set Table
	if(GlobalTrisetList.Create()==false)
		{
		MStdPrintf("**Triangle Set Table failed\n");
		GlobalDestroy();
		return false;
		}

	// Init Int Array List
	if(GlobalIntArrayList.Create()==false)
		{
		MStdPrintf("**Int Array Table failed\n");
		GlobalDestroy();
		return false;
		}


	// Init the input
	if(GlobalEventInput.Create(GlobalRefDevice)==false)
		{
		GlobalDestroy();
		return false;
		}

	// Init Task Queue
	if(GlobalTaskQueue.Create(GlobalRefDevice->getTimer()->getRealTime())==false)
		{
		MStdPrintf("**Task Queue failed\n");
		GlobalDestroy();
		return false;
		}

	// Init Task Queue
	if(GlobalTaskQueueInternal.Create(GlobalRefDevice->getTimer()->getRealTime())==false)
		{
		MStdPrintf("**Task Queue failed\n");
		GlobalDestroy();
		return false;
		}

	// Init Camera Key Control
	if(GlobalCameraControl.Create()==false)
		{
		GlobalDestroy();
		return false;
		}

	// Init GInternalEventID
	GlobalInternalEventID=0;

	// Initialize boolean variable
	GlobalInitialized=true;	
	return true;
	}


//////////////////////////////////////////////////
bool GlobalDestroy(void)
	{
	if(GlobalInitialized==false)
		{
		// Exit of not initialized	
		return true;
		}

	// Destroy Tables
	GlobalCameraControl.Destroy();
	GlobalTaskQueueInternal.Destroy();
	GlobalTaskQueue.Destroy();
	GlobalEventInput.Destroy();
	GlobalIntArrayList.Destroy();
	GlobalTrisetList.Destroy();
	GlobalAnimationList.Destroy();
	GlobalFontList.Destroy();
	GlobalMeshList.Destroy();
	GlobalSoundList.Destroy();
	GlobalTextureList.Destroy();;
	GlobalNodeList.Destroy();
	
	// Release Sound Device
	if(GlobalRefSoundDevice!=NULL)
		{
		GlobalRefSoundDevice->drop();
		GlobalRefSoundDevice=NULL;
		}

	// Release Graphics Device
	if(GlobalRefDevice!=NULL)
		{
		GlobalRefDevice->closeDevice();
		GlobalRefDevice->drop();
		GlobalRefDevice=NULL;
		}

	GlobalClear();

	MStdPrintf("ComineGL Library has Exited\n");
	return true;
	}



